package project.web_2.rest;

import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.util.JAXBSource;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.http.HTTPBinding;

import project.web_2.model.NoResumeFound;
import project.web_2.model.Resume;
import project.web_2.model.ResumeManager;



/**
 * Client de l'application.
 * @author Anton KISSELEFF & Nicolas LETHUILLIER
 */
public class MyClient {
	
	// ATTRIBUTS

	private static final QName qname = new QName("", "");
	private static final String url = "http://127.0.0.1:8080";
	
	private Service service;
	private JAXBContext jc;
	
	// CONSTRUCTEURS

	public MyClient() {
		try {
			jc = JAXBContext.newInstance(ResumeManager.class, Resume.class, NoResumeFound.class);
		} catch (JAXBException je) {
			System.out.println("Cannot create JAXBContext " + je);
		}
	}
	
	// COMMANDES
	
	/**
	 * Demande au serveur la liste de toutes les {@link Resume}.
	 * @throws JAXBException en cas d'échec de transmission
	 */
	public void getAllResumes() throws JAXBException {
		send("GET", new Resume());
	}
	
	/**
	 * Demande au serveur le {@link Resume} d'id id.
	 * @param id l'id du {@link Resume} à rechercher
	 * @throws JAXBException en cas d'échec de transmission
	 */
	public void getCity(int id) throws JAXBException {
		send("GET", new Resume(), "" + id);
	}
	
	/**
	 * Demande au serveur d'ajouter le {@link Resume} passé en argument.
	 * @param resume {@link Resume} à ajouter
	 * @throws JAXBException en cas d'échec de transmission
	 */
	public void addCity(Resume resume) throws JAXBException {
		send("PUT", resume);
	}

	/**
	 * Affiche le contenu de la source s.
	 * @param s la source à transformer pour l'affichage
	 */
	public void printSource(Source s) {
		try {
			System.out.println("============================= Response Received =========================================");
			TransformerFactory factory = TransformerFactory.newInstance();
			Transformer transformer = factory.newTransformer();
			try {
				transformer.transform(s, new StreamResult(System.out));
			} catch (TransformerException ex) {
				System.out.println("Erreur à la transformation !");
			}
			System.out.println("\n======================================================================");
		} catch (Exception e) {
			System.out.println(e);
		}
	}
	
	// OUTILS
	
	private void send(String method, Object arg) throws JAXBException {
		send(method, arg, null);
	}
	
	private void send(String method, Object arg, String urlArg) throws JAXBException {
		service = Service.create(qname);
		service.addPort(qname, HTTPBinding.HTTP_BINDING, url + (urlArg == null ? "" : "/?" + urlArg));
		Dispatch<Source> dispatcher = service.createDispatch(qname,
				Source.class, Service.Mode.MESSAGE);
		Map<String, Object> requestContext = dispatcher.getRequestContext();
		requestContext.put(MessageContext.HTTP_REQUEST_METHOD, method);
		Source result = dispatcher.invoke(new JAXBSource(jc, arg));
		printSource(result);
	}
	
	// MAIN

	public static void main(String args[]) throws Exception {
		MyClient client = new MyClient();
		client.getAllResumes();
	}
}
